package lib.gui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import lib.Base.Info;
import lib.Base.Profile;
import lib.Base.Request;
import lib.Com.Client;
import lib.Com.Container;
import lib.Com.KnownClient;
import lib.Com.Network;
import lib.Common.Path;
import lib.Common.UserId;
import lib.FileSystem.Check;
import lib.FileSystem.Make;
import lib.XML.XMLParser;
import lib.XML.XMLWriter;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;

import org.swixml.SwingEngine;

public class GuiMain {
	/**
	 * The Main container class from the user interface with all its components
	 */
	private SwingEngine engine;
	private JFrame frame;
	private JTable table_friendlist_input;
	private JPanel settingsTab;
	private JPanel profileMainTab;
	private JPanel profileFriendsTab;
	
	private GuiSettings gui_settings;
	private GuiMenu gui_menu;
	private GuiProfile mainProfile;
	private GuiProfileFriend friendProfile;
	// private GuiSearch searchTab;
	private GuiChat gui_chat;
	private JButton btn_logout;
	private Network networkConn;
	
	private String UID;
	private String UNAME;
	private String UPASS;
	
	// Friendlist table model to insert data
	private static DefaultTableModel dataModel = new DefaultTableModel(
			new Object[][] {}, new String[] { "Username", "Id" }) {

		private static final long serialVersionUID = 1L;

		public boolean isCellEditable(int rowIndex, int mColIndex) {
			return false;
		}
	};

	public GuiMain(String username, String userId, String password) {
		
		UID=userId.trim();
		UNAME=username.trim();
		UPASS=password.trim();
		
		// Render xml document
		try {
			engine = new SwingEngine(this);
			engine.render(new File(Path.GUI_PATH + "gui-main.xml")).setVisible(true);

			init();
			initActionListener();
			
			// Init gui components
			gui_menu = new GuiMenu(engine);
			gui_settings = new GuiSettings(settingsTab, engine);
			gui_chat = new GuiChat(frame.getLocation(), frame.getWidth());
			mainProfile = new GuiProfile(UID, true);
			profileMainTab.add(mainProfile.getPanel());	
			
			// Start network connection
			networkConn = new Network(userId);
			networkConn.start();
			frame.repaint();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	void init() {

		frame.getContentPane().setBackground(Color.DARK_GRAY);

		table_friendlist_input.setModel(dataModel);
		table_friendlist_input.removeColumn(table_friendlist_input
				.getColumnModel().getColumn(1));

		table_friendlist_input
				.addMouseListener(new java.awt.event.MouseAdapter() {

					public void mouseClicked(java.awt.event.MouseEvent e) {
						
						int row = table_friendlist_input.rowAtPoint(e
								.getPoint());
						int col = table_friendlist_input.columnAtPoint(e
								.getPoint());
						
						String userId = dataModel.getValueAt(row, col + 1).toString();
						String username = dataModel.getValueAt(row, col).toString();
						
						if (e.getClickCount() == 2) {
							try {
								gui_chat.addChatWindow(userId, username);
							} catch (Exception ex) {
								ex.printStackTrace();
							}
						}else if(e.getClickCount() == 1){
							
							Profile friend = null;
							Client client = null;
							
							try {
								KnownClient tmp = Container.knownClients.get(userId);
								
								if(Check.EXISTS(Path.XML_PATH_PROFILES + userId+".xml")){
									XMLParser parser = new XMLParser();
									friend = parser.ParseProfile(Path.XML_PATH_PROFILES + userId +".xml");
								}
								
								if(friend != null){
									// Send with timestamp
									client = new Client(tmp, new Request(friend.getLastChange(), UID, "profile", userId));
								}else{
									friend = new Profile();
									//Send without
									client = new Client(tmp, new Request(0, UID, "profile", userId));
								}

								client.start();
								Thread.sleep(500);
								
								friendProfile = new GuiProfileFriend(userId, false);
								profileFriendsTab.removeAll();
								profileFriendsTab.add(friendProfile.getPanel());
								
								
							} catch (Exception ex) {
								ex.printStackTrace();
							}
						}
					}
				});
	}


	void initActionListener() {
		btn_logout.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				File s = new File(Path.XML_PATH_MAIN+"friendlist.xml");
				if(s.exists()) {
					s.delete();
				}
				try {
					Thread.sleep(100);
					new XMLWriter().WriteSettings(Container.settings, Path.XML_PATH_MAIN+"settings.xml");
				}catch(Exception ew) {}
				File f = new File(Path.XML_PATH_MAIN+"friendlist.xml");
				if(f.exists()) {
					f.delete();
				}
				try {
					Thread.sleep(100);
					new XMLWriter().WriteFriendlist(Container.friendList, Path.XML_PATH_MAIN+"friendlist.xml");
				}catch(Exception ew) {}
				networkConn.Stop();
				String filename = UID+"-"+UNAME+".zip";
				new File(Path.USERS_DIR+filename).delete();
				try {
					Thread.sleep(100);
					ZipFile zipFile = new ZipFile(Path.USERS_DIR+filename);
					ZipParameters parameters = new ZipParameters();
					parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
					parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 
					parameters.setEncryptFiles(true);
					parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
					parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
					parameters.setPassword(UPASS);
					
					zipFile.addFolder(Path.RES_DIR, parameters);
				} catch (Exception z1) {
					z1.printStackTrace();
				}
				Make.CLEAR_DIR(Path.RES_DIR);
				System.exit(0);
			}
		});
	}
	
	public static void addFriend(String username, String userId){
		
		boolean found = false;
		
		for(int i = 0; i < dataModel.getRowCount(); i++){
			if(dataModel.getValueAt(0, i).equals(userId)){
				found = true;
			}
		}
		if(!found){
			dataModel.addRow(new Object[] { username, userId });
		}
	}

	public static void removeFriend(String userId) {
		for(int i = 0; i < dataModel.getRowCount(); i++){
			if(dataModel.getValueAt(0, i).equals(userId)){
				dataModel.removeRow(i);
			}
		}
	}
}